﻿using eLoan.Models;
using GsmLink;
using GsmLink.Comm;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using System.Web.Mvc;

namespace eLoan.Controllers
{
    public class WorkspaceController : BaseController
    {

        public ActionResult Index()
        {
            try
            {
                return RedirectToAction("Index", "Home");
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult LoanPayment(string branchCode, int? agentID, string searchText = "")
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPayment);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetLoanPaymentModel(db, branchCode, agentID, searchText, User.Identity.Name);
                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult CashPayment(string branchCode, int? agentID, string searchText = "")
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPayment);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetLoanPaymentModel(db, branchCode, agentID, searchText, User.Identity.Name);
                return View("LoanPayment", model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult ChequePayment(string branchCode, int? agentID, string searchText = "")
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPayment);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetLoanPaymentModel(db, branchCode, agentID, searchText, User.Identity.Name, false);
                return View("LoanPayment", model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        [HttpPost]
        public ActionResult SaveLoanPayment(LoanPaymentModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPayment);

                if (command == AdministrationHelper.DBCommand.Save.ToString())
                {
                    var db = new DatabaseContext();

                    foreach (var item in model.PaymentItems)
                    {
                        if (item.Amount > 0)
                        {
                            var pay = new LoanPayment();
                            pay.DocumentNo = item.DocumentNo;
                            pay.Amount = item.Amount;
                            pay.Penalty = item.Penalty;
                            pay.PaymentDate = model.PaymentDate;
                            pay.PaymentTypeID = item.PaymentTypeID;

                            switch (item.PaymentTypeID)
                            {
                                case (int)AdministrationHelper.PaymentType.CashN:
                                case (int)AdministrationHelper.PaymentType.CashR:
                                case (int)AdministrationHelper.PaymentType.FundTransfer:
                                    {
                                        pay.StatusID = (int)AdministrationHelper.LoanPaymentStatus.Posted;
                                        break;
                                    }
                                case (int)AdministrationHelper.PaymentType.ChequeN:
                                case (int)AdministrationHelper.PaymentType.ChequeR:
                                    {
                                        pay.StatusID = (int)AdministrationHelper.LoanPaymentStatus.ForClearing;
                                        break;
                                    }
                            }

                            pay.IsVoid = false;

                            db.LoanPayments.Add(pay);
                        }
                    }

                    db.SaveChanges();
                }
                else if (command == AdministrationHelper.DBCommand.Export.ToString() && model.PaymentItems != null)
                {
                    using (ExcelPackage package = new ExcelPackage())
                    {
                        string workBookName = "LoanPayment";
                        string centerText = "Loan Payment";

                        var ws = ReportHelper.SetWorksheet(package, workBookName, centerText);

                        List<string> headerNames = new List<string>();
                        headerNames.Add("Document No");
                        headerNames.Add("Borrower");
                        headerNames.Add("Penalty");
                        headerNames.Add("Amount");
                        headerNames.Add("Outstanding Balance");
                        headerNames.Add("Receivable");
                        headerNames.Add("Total Payment");
                        headerNames.Add("Short/Over");
                        headerNames.Add("Payment Start Date");
                        headerNames.Add("Maturity Date");
                        headerNames.Add("Payment Type");
                        headerNames.Add("Contact Numbers");
                        headerNames.Add("Loan Status");

                        char columnStart = 'A';
                        int rowStart = 1;
                        ws = ReportHelper.SetWorksheetHeader(ws, headerNames, columnStart, rowStart);

                        var nextRow = ++rowStart;
                        for (var i = 0; i < model.PaymentItems.Count(); i++)
                        {
                            var nextColumn = columnStart;

                            var headerValues = new List<string>();
                            headerValues.Add(model.PaymentItems[i].DocumentNo);
                            headerValues.Add(model.PaymentItems[i].BorrowerName);
                            headerValues.Add(model.PaymentItems[i].Penalty.ToString("#,###,##0.00"));
                            headerValues.Add(model.PaymentItems[i].Amount.ToString("#,###,##0.00"));
                            headerValues.Add(model.PaymentItems[i].OutstandingBalance.ToString("#,###,##0.00"));
                            headerValues.Add(model.PaymentItems[i].Receivable.ToString("#,###,##0.00"));
                            headerValues.Add(model.PaymentItems[i].TotalPayment.ToString("#,###,##0.00"));
                            headerValues.Add(model.PaymentItems[i].ShortOver.ToString("#,###,##0.00"));

                            if (model.PaymentItems[i].PaymentStartDate.HasValue)
                            {
                                headerValues.Add(model.PaymentItems[i].PaymentStartDate.GetValueOrDefault().ToString("MMM/dd/yyyy"));
                            }
                            else
                            {
                                headerValues.Add(string.Empty);
                            }

                            if (model.PaymentItems[i].PaymentEndDate.HasValue)
                            {
                                headerValues.Add(model.PaymentItems[i].PaymentEndDate.GetValueOrDefault().ToString("MMM/dd/yyyy"));
                            }
                            else
                            {
                                headerValues.Add(string.Empty);
                            }


                            var paymentType = model.PaymentItems[i].PaymentTypeName;

                            headerValues.Add(paymentType);
                            headerValues.Add(model.PaymentItems[i].ContactNumbers);
                            headerValues.Add(model.PaymentItems[i].LoanStatus);

                            ws = ReportHelper.SetWorksheetRows(ws, headerValues, nextColumn, nextRow);

                            ++nextRow;
                        }

                        string fileName = @"LoanPayment_" + string.Format("{0:ddMMMyyy}", DateTime.Now) + "_" + DateTime.Now.Second.ToString() + ".xlsx";
                        string path = ServerBranchReportsPath + fileName;
                        var newFileInfo = new FileInfo(path);
                        if (!newFileInfo.Directory.Exists) Directory.CreateDirectory(newFileInfo.Directory.FullName);

                        package.SaveAs(newFileInfo);
                        ReportHelper.DownloadFile(ServerReportsUrlPath, ClientReportsPath, fileName);
                    }
                }

                string action = model.IsCashPayment ? "CashPayment" : "ChequePayment";

                return RedirectToAction(action, "Workspace",
                    new
                    {
                        branchCode = model.SelectedBranchCode,
                        agentID = model.SelectedAgentID,
                        searchText = model.SearchText
                    });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult ChequeClearing(string branchCode, int? agentID, DateTime? fromDate, DateTime? toDate)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.ChequeClearing);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetChequeClearingModel(db, branchCode, agentID, fromDate, toDate, User.Identity.Name);
                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        //[HttpPost]
        //public ActionResult SaveLoanPayment(LoanPaymentModel model, string command)
        //{
        //    try
        //    {
        //        CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPayment);

        //        if (command == AdministrationHelper.DBCommand.Save.ToString())
        //        {
        //            var db = new DatabaseContext();

        //            foreach (var item in model.PaymentItems)
        //            {
        //                if (item.Amount > 0)
        //                {
        //                    var pay = new LoanPayment();
        //                    pay.DocumentNo = item.DocumentNo;
        //                    pay.Amount = item.Amount;
        //                    pay.Penalty = item.Penalty;
        //                    pay.PaymentDate = model.PaymentDate;
        //                    pay.PaymentTypeID = item.PaymentTypeID;
        //                    pay.StatusID = (int)AdministrationHelper.LoanPaymentStatus.Posted;
        //                    pay.IsVoid = false;

        //                    db.LoanPayments.Add(pay);
        //                }
        //            }

        //            db.SaveChanges();
        //        }
        //        else if (command == AdministrationHelper.DBCommand.Export.ToString() && model.PaymentItems != null)
        //        {
        //            using (ExcelPackage package = new ExcelPackage())
        //            {
        //                string workBookName = "LoanPayment";
        //                string centerText = "Loan Payment";

        //                var ws = ReportHelper.SetWorksheet(package, workBookName, centerText);

        //                List<string> headerNames = new List<string>();
        //                headerNames.Add("Document No");
        //                headerNames.Add("Borrower");
        //                headerNames.Add("Penalty");
        //                headerNames.Add("Amount");
        //                headerNames.Add("Outstanding Balance");
        //                headerNames.Add("Receivable");
        //                headerNames.Add("Total Payment");
        //                headerNames.Add("Short/Over");
        //                headerNames.Add("Payment Start Date");
        //                headerNames.Add("Maturity Date");
        //                headerNames.Add("Payment Type");
        //                headerNames.Add("Contact Numbers");
        //                headerNames.Add("Loan Status");

        //                char columnStart = 'A';
        //                int rowStart = 1;
        //                ws = ReportHelper.SetWorksheetHeader(ws, headerNames, columnStart, rowStart);

        //                var nextRow = ++rowStart;
        //                for (var i = 0; i < model.PaymentItems.Count(); i++)
        //                {
        //                    var nextColumn = columnStart;

        //                    var headerValues = new List<string>();
        //                    headerValues.Add(model.PaymentItems[i].DocumentNo);
        //                    headerValues.Add(model.PaymentItems[i].BorrowerName);
        //                    headerValues.Add(model.PaymentItems[i].Penalty.ToString("#,###,##0.00"));
        //                    headerValues.Add(model.PaymentItems[i].Amount.ToString("#,###,##0.00"));
        //                    headerValues.Add(model.PaymentItems[i].OutstandingBalance.ToString("#,###,##0.00"));
        //                    headerValues.Add(model.PaymentItems[i].Receivable.ToString("#,###,##0.00"));
        //                    headerValues.Add(model.PaymentItems[i].TotalPayment.ToString("#,###,##0.00"));
        //                    headerValues.Add(model.PaymentItems[i].ShortOver.ToString("#,###,##0.00"));

        //                    if (model.PaymentItems[i].PaymentStartDate.HasValue)
        //                    {
        //                        headerValues.Add(model.PaymentItems[i].PaymentStartDate.GetValueOrDefault().ToString("MMM/dd/yyyy"));
        //                    }
        //                    else
        //                    {
        //                        headerValues.Add(string.Empty);
        //                    }

        //                    if (model.PaymentItems[i].PaymentEndDate.HasValue)
        //                    {
        //                        headerValues.Add(model.PaymentItems[i].PaymentEndDate.GetValueOrDefault().ToString("MMM/dd/yyyy"));
        //                    }
        //                    else
        //                    {
        //                        headerValues.Add(string.Empty);
        //                    }


        //                    var paymentType = model.PaymentItems[i].PaymentTypeName;

        //                    headerValues.Add(paymentType);
        //                    headerValues.Add(model.PaymentItems[i].ContactNumbers);
        //                    headerValues.Add(model.PaymentItems[i].LoanStatus);

        //                    ws = ReportHelper.SetWorksheetRows(ws, headerValues, nextColumn, nextRow);

        //                    ++nextRow;
        //                }

        //                string fileName = @"LoanPayment_" + string.Format("{0:ddMMMyyy}", DateTime.Now) + "_" + DateTime.Now.Second.ToString() + ".xlsx";
        //                string path = ServerBranchReportsPath + fileName;
        //                var newFileInfo = new FileInfo(path);
        //                if (!newFileInfo.Directory.Exists) Directory.CreateDirectory(newFileInfo.Directory.FullName);

        //                package.SaveAs(newFileInfo);
        //                ReportHelper.DownloadFile(ServerReportsUrlPath, ClientReportsPath, fileName);
        //            }
        //        }

        //        return RedirectToAction("LoanPayment", "Workspace",
        //            new
        //            {
        //                branchCode = model.SelectedBranchCode,
        //                agentID = model.SelectedAgentID,
        //                searchText = model.SearchText
        //            });
        //    }
        //    catch (Exception ex)
        //    {
        //        return View("Error", ex);
        //    }
        //}

        [HttpPost]
        public ActionResult SaveChequeClearing(ChequeClearingModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPayment);

                var db = new DatabaseContext();

                if (command == AdministrationHelper.DBCommand.Dishonor.ToString())
                {

                    foreach (var item in model.Items)
                    {
                        if (item.IsSelected)
                        {
                            var pay = db.LoanPayments.Where(w => w.ID == item.ID).SingleOrDefault();
                            pay.StatusID = (int)AdministrationHelper.LoanPaymentStatus.Dishonored;
                            pay.Remarks = item.Remarks;

                            db.Entry(pay).State = System.Data.EntityState.Modified;
                            db.SaveChanges();
                        }
                    }
                }
                else if (command == AdministrationHelper.DBCommand.Clear.ToString())
                {
                    foreach (var item in model.Items)
                    {
                        if (item.IsSelected)
                        {
                            var pay = db.LoanPayments.Where(w => w.ID == item.ID).SingleOrDefault();
                            pay.StatusID = (int)AdministrationHelper.LoanPaymentStatus.Cleared;
                            pay.Remarks = item.Remarks;

                            db.Entry(pay).State = System.Data.EntityState.Modified;
                            db.SaveChanges();
                        }
                    }
                }
                else if (command == AdministrationHelper.DBCommand.Cancel.ToString())
                {
                    foreach (var item in model.Items)
                    {
                        if (item.IsSelected)
                        {
                            var pay = db.LoanPayments.Where(w => w.ID == item.ID).SingleOrDefault();
                            pay.StatusID = (int)AdministrationHelper.LoanPaymentStatus.Cancelled;
                            pay.Remarks = item.Remarks;

                            db.Entry(pay).State = System.Data.EntityState.Modified;
                            db.SaveChanges();
                        }
                    }
                }


                return RedirectToAction("ChequeClearing", "Workspace",
                    new
                    {
                        branchCode = model.SelectedBranchCode,
                        agentID = model.SelectedAgentID,
                        fromDate = model.FromDate,
                        toDate = model.ToDate
                    });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult VoidLoanPayment(string branchCode, bool? isAgentSelected, int? agentID, DateTime? datePosted, string searchText)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.VoidLoanPayment);

                var db = new DatabaseContext();
                var postPaymentModel = WorkspaceHelper.GetVoidLoanPaymentModel(db, branchCode, isAgentSelected, agentID, datePosted, searchText, User.Identity.Name);
                return View(postPaymentModel);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        [HttpPost]
        public ActionResult SaveVoidLoanPayment(VoidPaymentModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.VoidLoanPayment);

                using (var db = new DatabaseContext())
                {
                    if (command == AdministrationHelper.DBCommand.Post.ToString())
                    {
                        foreach (var item in model.VoidLoanPaymentItems)
                        {
                            if (item.IsSelected)
                            {
                                var payment = db.LoanPayments.Where(w => w.ID == item.PaymentID).SingleOrDefault<LoanPayment>();
                                payment.StatusID = (int)AdministrationHelper.LoanPaymentStatus.Posted;

                                db.Entry(payment).State = System.Data.EntityState.Modified;

                            }
                        }

                        db.SaveChanges();
                    }
                    else if (command == AdministrationHelper.DBCommand.Void.ToString()
                                && model.VoidLoanPaymentItems != null)
                    {
                        foreach (var item in model.VoidLoanPaymentItems)
                        {
                            if (item.IsSelected)
                            {
                                var payment = db.LoanPayments.Where(w => w.ID == item.PaymentID).SingleOrDefault<LoanPayment>();
                                payment.IsVoid = true;
                                payment.VoidDate = DateTime.Now;
                                payment.VoidBy = User.Identity.Name;
                                payment.Remarks = item.Remarks;
                                db.Entry(payment).State = System.Data.EntityState.Modified;

                            }
                        }

                        db.SaveChanges();
                    }
                    else
                    {
                        // refreshed
                    }
                }

                return RedirectToAction("VoidLoanPayment", "Workspace",
                    new
                    {
                        branchCode = model.SelectedBranchCode,
                        isAgentSelected = model.IsAgentSelected,
                        agentID = model.SelectedAgentID,
                        datePosted = model.DatePosted,
                        searchText = model.SearchText
                    });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult RequestCloseLoan(string branchCode, string searchText)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.RequestCloseLoan);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetRequestCloseLoanModel(db, branchCode, searchText, User.Identity.Name);
                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        [HttpPost]
        public ActionResult SaveRequestCloseLoan(CloseLoanModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.RequestCloseLoan);

                using (var db = new DatabaseContext())
                {
                    if (command == AdministrationHelper.DBCommand.Save.ToString() && model.CloseLoanItems != null)
                    {
                        foreach (var item in model.CloseLoanItems)
                        {
                            if (item.IsSelected)
                            {
                                var loan = db.Loans.Where(w => w.DocumentNo == item.DocumentNo).SingleOrDefault<Loan>();
                                loan.StatusID = (int)AdministrationHelper.LoanStatus.RequestClose;
                                loan.RemarkID = item.RemarkID;
                                db.Entry(loan).State = System.Data.EntityState.Modified;
                            }
                        }

                        db.SaveChanges();
                    }
                    else
                    {
                        // refreshed
                    }
                }

                return RedirectToAction("RequestCloseLoan", "Workspace",
                    new
                    {
                        branchCode = model.SelectedBranchCode,
                        searchText = model.SearchText
                    });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult CloseLoan(string branchCode, string searchText)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.CloseLoan);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetCloseLoanModel(db, branchCode, searchText, User.Identity.Name);
                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        [HttpPost]
        public ActionResult SaveCloseLoan(CloseLoanModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.CloseLoan);

                using (var db = new DatabaseContext())
                {
                    if (command == AdministrationHelper.DBCommand.Save.ToString() && model.CloseLoanItems != null)
                    {
                        foreach (var item in model.CloseLoanItems)
                        {
                            if (item.IsSelected)
                            {
                                var loan = db.Loans.Where(w => w.DocumentNo == item.DocumentNo).SingleOrDefault<Loan>();
                                loan.RemarkID = item.RemarkID;
                                loan.StatusID = (int)AdministrationHelper.LoanStatus.Closed;
                                loan.DateClosed = DateTime.Today;
                                db.Entry(loan).State = System.Data.EntityState.Modified;
                            }
                        }

                        db.SaveChanges();
                    }
                    else if (command == AdministrationHelper.DBCommand.Cancel.ToString() && model.CloseLoanItems != null)
                    {
                        foreach (var item in model.CloseLoanItems)
                        {
                            if (item.IsSelected)
                            {
                                var loan = db.Loans.Where(w => w.DocumentNo == item.DocumentNo).SingleOrDefault<Loan>();
                                loan.RemarkID = null;
                                loan.StatusID = (int)AdministrationHelper.LoanStatus.ReleasedToBorrower;
                                db.Entry(loan).State = System.Data.EntityState.Modified;
                            }
                        }

                        db.SaveChanges();
                    }
                    else
                    {
                        // refreshed
                    }
                }

                return RedirectToAction("CloseLoan", "Workspace",
                    new
                    {
                        branchCode = model.SelectedBranchCode,
                        searchText = model.SearchText
                    });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult LoanPenalty(string branchCode, string searchText)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPenalty);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetLoanPenaltyModel(db, branchCode, searchText, User.Identity.Name);
                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult PrintDemandLetter(string documentNo, string branchCode, string searchText, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanPenalty);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetLoanPenaltyModel(db, branchCode, searchText, User.Identity.Name);

                LoanPenaltyQueryModel demandItem;
                if (command == "Penalty")
                    demandItem = model.PenaltyList.Where(w => w.DocumentNo == documentNo).SingleOrDefault<LoanPenaltyQueryModel>();
                else if (command == "Delayed")
                    demandItem = model.DelayedLoans.Where(w => w.DocumentNo == documentNo).SingleOrDefault<LoanPenaltyQueryModel>();
                else
                    demandItem = model.DelinquentLoans.Where(w => w.DocumentNo == documentNo).SingleOrDefault<LoanPenaltyQueryModel>();

                string path = System.Configuration.ConfigurationManager.AppSettings["DemandLetterPath"].ToString();
                var fileInfo = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + path);

                using (ExcelPackage package = new ExcelPackage(fileInfo))
                {

                    var ws = package.Workbook.Worksheets["DEMAND LETTER"];

                    ws.Cells["J11"].Value = DateTime.Today.ToString("MMMM dd, yyyy");
                    ws.Cells["B13"].Value = demandItem.BorrowerName;
                    ws.Cells["D21"].Value = demandItem.BorrowerName;

                    ws.Cells["B14"].Value = demandItem.BorrowerAddress;

                    var totalAmount = demandItem.OutstandingBalance + demandItem.TotalPenalty + demandItem.TotalAdditionalInterest;
                    ws.Cells["F25"].Value = totalAmount.ToString("#,###,##0.00");
                    ws.Cells["G32"].Value = totalAmount.ToString("#,###,##0.00");
                    ws.Cells["J25"].Value = demandItem.DueDate.ToString("MMMM dd, yyyy");

                    ws.Cells["G28"].Value = demandItem.OutstandingBalance.ToString("#,###,##0.00");
                    ws.Cells["G29"].Value = demandItem.TotalPenalty.ToString("#,###,##0.00");
                    ws.Cells["G30"].Value = demandItem.TotalAdditionalInterest.ToString("#,###,##0.00");

                    string fileName = @"DemandLetter_" + string.Format("{0:ddMMMyyy}", DateTime.Now) + "_" + DateTime.Now.Second.ToString() + ".xlsx";
                    string reportsPath = ServerBranchReportsPath + fileName;
                    var newFileInfo = new FileInfo(reportsPath);
                    if (!newFileInfo.Directory.Exists) Directory.CreateDirectory(newFileInfo.Directory.FullName);

                    package.SaveAs(newFileInfo);
                    ReportHelper.DownloadFile(ServerReportsUrlPath, ClientReportsPath, fileName);
                }


                return RedirectToAction("LoanPenalty", "Workspace", new { branchCode = branchCode, searchText = searchText });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult SaveLoanPenalty(LoanPenaltyModel model, string command)
        {
            try
            {
                var db = new DatabaseContext();

                if (command == AdministrationHelper.DBCommand.SaveDelayed.ToString())
                {
                    foreach (var item in model.DelayedLoans)
                    {
                        if (item.TotalPenalty > 0 || item.AdditionalInterest > 0)
                        {
                            var penalty = new LoanPenalty();
                            penalty.DocumentNo = item.DocumentNo;
                            penalty.Penalty = item.TotalPenalty;
                            penalty.AdditionalInterest = item.TotalAdditionalInterest;
                            penalty.Remarks = item.Remarks;
                            penalty.DueDate = item.DueDate;
                            penalty.PenaltyDate = DateTime.Today;
                            penalty.EncodedBy = User.Identity.Name;

                            db.LoanPenalties.Add(penalty);
                        }
                    }

                    db.SaveChanges();
                }
                else if (command == AdministrationHelper.DBCommand.SaveDelinquent.ToString())
                {
                    foreach (var item in model.DelinquentLoans)
                    {
                        if (item.TotalPenalty > 0 || item.AdditionalInterest > 0)
                        {
                            var penalty = new LoanPenalty();
                            penalty.DocumentNo = item.DocumentNo;
                            penalty.Penalty = item.TotalPenalty;
                            penalty.AdditionalInterest = item.TotalAdditionalInterest;
                            penalty.Remarks = item.Remarks;
                            penalty.DueDate = item.DueDate;
                            penalty.PenaltyDate = DateTime.Today;
                            penalty.EncodedBy = User.Identity.Name;

                            db.LoanPenalties.Add(penalty);
                        }
                    }

                    db.SaveChanges();
                }
                else
                {
                    // refresh
                }

                return RedirectToAction("LoanPenalty", new { branchCode = model.SelectedBranchCode, searchText = model.SearchText });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult LoanNotification(string branchCode, int? agentID, bool? isModemFound = true)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanNotification);

                var model = new LoanNotificationModel();
                var db = new DatabaseContext();
                model = WorkspaceHelper.GetLoanNotificationModel(db, User.Identity.Name, branchCode, agentID, isModemFound);

                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult RefreshLoanNotification(LoanNotificationModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.LoanNotification);

                if (command == AdministrationHelper.DBCommand.SendNotification.ToString())
                {
                    //var portName = System.Configuration.ConfigurationManager.AppSettings["GSMModemCOMPort"].ToString();

                    var portNames = SerialPort.GetPortNames();
                    var modemPort = "";

                    foreach (var portName in portNames)
                    {
                        modemPort = portName;
                        break;
                    }

                    if (!string.IsNullOrEmpty(modemPort))
                    {
                        model.IsModemFound = true;
                        SendNotification(modemPort, model);
                    }
                    else
                    { model.IsModemFound = false; }

                }
                else
                {
                    // refresh or select branch
                    model.IsModemFound = true;
                }

                return RedirectToAction("LoanNotification",
                    new
                    {
                        branchCode = model.SelectedBranchCode,
                        agentID = model.SelectedAgentID,
                        isModemFound = model.IsModemFound
                    });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult CollectionReconciliation(string branchCode, DateTime? collectionDate, string searchText)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetCollectionReconciliationModel(db, branchCode, collectionDate, searchText, User.Identity.Name);

                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult RefreshCollectionReconciliation(CollectionReconciliationModel model)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);

                return RedirectToAction("CollectionReconciliation", new { branchCode = model.SelectedBranchCode, collectionDate = model.CollectionDate, searchText = model.SearchText });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult CollectionReconciliationAdd(string branchCode, DateTime? collectionDate)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);

                var db = new DatabaseContext();
                var model = WorkspaceHelper.GetCollectionReconciliationAddModel(db, branchCode, collectionDate);

                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        [HttpPost]
        public ActionResult CollectionReconciliationAdd(CollectionReconciliationAddModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);

                using (var db = new DatabaseContext())
                {
                    if (command == AdministrationHelper.DBCommand.Save.ToString())
                    {
                        foreach (var item in model.CollectionReconciliationItems)
                        {
                            var collection = new CollectionReconciliation();
                            collection.Date = item.Date;
                            collection.BranchCode = item.BranchCode;
                            collection.AgentID = item.AgentID;
                            collection.CashDeposited = item.CashDeposited;
                            collection.DeductedToChequeAdvancePayment = item.DeductedToChequeAdvancePayment;
                            collection.DeductedToChequeSavings = item.DeductedToChequeSavings;
                            collection.UsedForLoanRelease = item.UsedForLoanRelease;
                            collection.UsedInWithdrawalOfSavings = item.UsedInWithdrawalOfSavings;
                            collection.Others = item.Others;
                            collection.Remarks = item.Remarks;
                            collection.Total = item.Total;
                            collection.StatusID = item.StatusID;
                            collection.TotalCollectionPerRecord = item.TotalCollectionPerRecord;
                            collection.Difference = item.Difference;

                            db.CollectionReconciliations.Add(collection);
                        }

                        db.SaveChanges();
                    }
                    else
                    {
                        // cancelled
                    }
                }

                return RedirectToAction("CollectionReconciliation", new { branchCode = model.SelectedBranchCode, collectionDate = model.CollectionDate, searchText = string.Empty });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        public ActionResult CollectionReconciliationEdit(int? id)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);

                var db = new DatabaseContext();

                var model = new CollectionReconciliationEditModel();
                model.CollectionReconciliationItem = db.CollectionReconciliations.Where(w => w.ID == id).SingleOrDefault<CollectionReconciliation>();
                model.AgentName = AdministrationHelper.GetAgentName(model.CollectionReconciliationItem.AgentID);
                model.BranchName = AdministrationHelper.GetBranchName(model.CollectionReconciliationItem.BranchCode);

                return View(model);
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        [HttpPost]
        public ActionResult CollectionReconciliationEdit(CollectionReconciliationEditModel model, string command)
        {
            try
            {
                CheckUserPageAccess(AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);

                using (var db = new DatabaseContext())
                {
                    if (command == AdministrationHelper.DBCommand.Save.ToString())
                    {

                        db.Entry(model.CollectionReconciliationItem).State = System.Data.EntityState.Modified;
                        db.SaveChanges();
                    }
                    else
                    {
                        // cancelled
                    }
                }

                return RedirectToAction("CollectionReconciliation", new { branchCode = model.CollectionReconciliationItem.BranchCode, collectionDate = model.CollectionReconciliationItem.Date, searchText = string.Empty });
            }
            catch (Exception ex)
            {
                return View("Error", ex);
            }
        }

        #region SMS

        static GsmDevice device = null;

        [STAThread]
        void SendNotification(string portName, LoanNotificationModel model)
        {
            try
            {
                device = new GsmDevice("GSMModem", CommDriverFactory.GetCommDriver(portName));
                device.Connected += new EventHandler(Connected);
                device.Disconnected += new EventHandler(Disconnected);
                device.BatteryLevelChanged += new BatteryLevelChangedEventHandler(BatteryLevelChanged);
                device.SignalQualityChanged += new SignalQualityChangedEventHandler(SignalQualityChanged);
                device.MessageReceived += new MessageReceivedEventHandler(MessageReceived);
                device.SendMessageSucceeded += new SendMessageResultEventHandler(SendMessageSucceeded);
                device.SendMessageFailed += new SendMessageResultEventHandler(SendMessageFailed);

                device.Start();

                var db = new DatabaseContext();

                var msgForDelayed = db.Notifications.Where(w => w.ID == model.SelectedDelayedNotificationID).SingleOrDefault<Notification>().Message;
                var delayedLoans = new List<LoansForNotificationModel>();

                if (model.DelayedLoans != null)
                {
                    delayedLoans = model.DelayedLoans.Where(w => w.IsSelected == true).ToList();
                }

                for (var i = 0; i < delayedLoans.Count(); i++)
                {
                    var contacts = delayedLoans[i].ContactNumbers.Split(' ');
                    var message = string.Format(msgForDelayed, delayedLoans[i].BorrowerName, delayedLoans[i].ShortOver.ToString("#,###,##0.00").Replace("-", ""), DateTime.Now.ToString("MMMM dd, yyyy"));

                    SendNotificationToList(contacts, message);
                }


                var msgForDelinquent = db.Notifications.Where(w => w.ID == model.SelectedDelingquentNotificationID).SingleOrDefault<Notification>().Message;
                var delinquentLoans = new List<LoansForNotificationModel>();

                if (model.DelinquentLoans != null)
                {
                    delinquentLoans = model.DelinquentLoans.Where(w => w.IsSelected == true).ToList();
                }

                for (var i = 0; i < delinquentLoans.Count(); i++)
                {
                    var contacts = delinquentLoans[i].ContactNumbers.Split(' ');
                    var endDate = delinquentLoans[i].PaymentEndDate.HasValue ? delinquentLoans[i].PaymentEndDate.GetValueOrDefault().ToString("MMMM dd, yyyy") : string.Empty;
                    var message = string.Format(msgForDelinquent, delinquentLoans[i].BorrowerName, delinquentLoans[i].ShortOver.ToString("#,###,##0.00").Replace("-", ""), endDate);

                    SendNotificationToList(contacts, message);
                }

                var msgForRenewal = db.Notifications.Where(w => w.ID == model.SelectedRenewalNotificationID).SingleOrDefault<Notification>().Message;
                var renewalLoans = new List<LoansForRenewalModel>();

                if (model.LoanForRenewal != null)
                {
                    renewalLoans = model.LoanForRenewal.Where(w => w.IsSelected == true).ToList();
                }

                for (var i = 0; i < renewalLoans.Count(); i++)
                {
                    var contacts = renewalLoans[i].ContactNumbers.Split(' ');
                    var message = string.Format(msgForRenewal, renewalLoans[i].BorrowerName, string.Empty, string.Empty);

                    SendNotificationToList(contacts, message);
                }

                var msgForProspects = db.Notifications.Where(w => w.ID == model.SelectedProspectNotificationID).SingleOrDefault<Notification>().Message;
                var prospects = new List<LoanProspectModel>();

                if (model.LoanProspects != null)
                {
                    prospects = model.LoanProspects.Where(w => w.IsSelected == true).ToList();
                }

                for (var i = 0; i < prospects.Count(); i++)
                {
                    var contacts = prospects[i].ContactNumbers.Split(' ');
                    var message = string.Format(msgForProspects, prospects[i].ProspectName, string.Empty, string.Empty);

                    SendNotificationToList(contacts, message);
                }

                do
                { /* wait until all queued messages are sent; */ }
                while (device.NumberOfMessagesToSend > 0);
                device.Stop();
            }
            catch (Exception ex)
            {
                device.Stop();
                throw ex;
            }
        }

        private void SendNotificationToList(string[] contacts, string message)
        {
            var countryCode = "63";

            for (var i = 0; i < contacts.Count(); i++)
            {
                if (message.Length <= 160)
                {
                    SmsMessage sms = new SmsMessage(countryCode + contacts[i], message);
                    sms.Tag = i + 1;
                    device.SendMessage(sms);
                }
                else if (message.Length + 5 > 160 && message.Length + 5 <= 320)
                {
                    string msg0, msg1 = string.Empty;

                    msg0 = "(1/2)" + message.Substring(0, 155);
                    SmsMessage sms0 = new SmsMessage(countryCode + contacts[i], msg0);
                    sms0.Tag = i + 1;
                    device.SendMessage(sms0);

                    msg1 = "(2/2)" + message.Substring(155, message.Length + 5 - 160);
                    SmsMessage sms1 = new SmsMessage(countryCode + contacts[i], msg1);
                    sms1.Tag = i + 1;
                    device.SendMessage(sms1);
                }
                else if (message.Length + 5 > 320 && message.Length + 5 <= 480)
                {
                    string msg0, msg1, msg2 = string.Empty;

                    msg0 = "(1/3)" + message.Substring(0, 155);
                    SmsMessage sms0 = new SmsMessage(countryCode + contacts[i], msg0);
                    sms0.Tag = i + 1;
                    device.SendMessage(sms0);

                    msg1 = "(2/3)" + message.Substring(155, 155);
                    SmsMessage sms1 = new SmsMessage(countryCode + contacts[i], msg1);
                    sms1.Tag = i + 1;
                    device.SendMessage(sms1);

                    msg2 = "(3/3)" + message.Substring(310, message.Length + 10 - 320);
                    SmsMessage sms2 = new SmsMessage(countryCode + contacts[i], msg2);
                    sms2.Tag = i + 1;
                    device.SendMessage(sms2);
                }
                else
                {
                    string msg0, msg1, msg2, msg3 = string.Empty;

                    msg0 = "(1/4)" + message.Substring(0, 155);
                    SmsMessage sms0 = new SmsMessage(countryCode + contacts[i], msg0);
                    sms0.Tag = i + 1;
                    device.SendMessage(sms0);

                    msg1 = "(2/4)" + message.Substring(155, 155);
                    SmsMessage sms1 = new SmsMessage(countryCode + contacts[i], msg1);
                    sms1.Tag = i + 2;
                    device.SendMessage(sms1);

                    msg2 = "3/4" + message.Substring(310, 155);
                    SmsMessage sms2 = new SmsMessage(countryCode + contacts[i], msg2);
                    sms2.Tag = i + 3;
                    device.SendMessage(sms2);

                    msg3 = "(4/4)" + message.Substring(465, message.Length + 15 - 480);
                    SmsMessage sms3 = new SmsMessage(countryCode + contacts[i], msg3);
                    sms3.Tag = i + 4;
                    device.SendMessage(sms3);
                }

            }
        }

        private void Connected(object sender, EventArgs e)
        {
            Response.Write("\nGSM device connected.\n");
            Response.Write(string.Format("Manufacturer: {0}", device.Manufacturer));
            Response.Write(string.Format("Model: {0}", device.Model));
            Response.Write(string.Format("Serial #: {0}", device.SerialNumber));
            Response.Write(string.Format("Is using battery? {0}", device.IsUsingBattery));
            Response.Write(string.Format("Battery level: {0}", device.BatteryLevel));
            Response.Write(string.Format("Signal quality: {0}\n", device.SignalQuality));
        }

        private void Disconnected(object sender, EventArgs e)
        {
            Response.Write("\nGSM device disconnected.\n");
        }

        private void BatteryLevelChanged(object sender, BatteryLevelChangedEventArgs e)
        {
            Response.Write(string.Format("\nGSM device's battery level has changed: {0}\n", e.BatteryLevel));
        }

        private void SignalQualityChanged(object sender, SignalQualityChangedEventArgs e)
        {
            Response.Write(string.Format("\nGSM device's signal quality has changed: {0}\n", e.SignalQuality));
        }

        private void MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            int messageCount = e.Messages.GetLength(0);
            if (messageCount > 0)
            {
                Response.Write(string.Format("\n{0} message(s) received:\n", messageCount));
                for (int i = 0; i < messageCount; i++)
                {
                    Response.Write(string.Format("\nMessage # {0}", i + 1));
                    Response.Write(string.Format("Status: {0}", e.Messages[i].Status.ToString()));
                    Response.Write(string.Format("Sender: {0}", e.Messages[i].Sender));
                    Response.Write(string.Format("Time stamp: {0}", e.Messages[i].TimeStamp));
                    Response.Write(string.Format("Encoding: {0}", e.Messages[i].EncodingScheme.ToString()));
                    if (e.Messages[i].EncodingScheme == EncodingScheme.Text)
                        Response.Write(string.Format("Body: {0}", (string)e.Messages[i].Body));
                    else
                        Response.Write(string.Format("Body: <cannot be displayed>"));
                }
            }
        }

        private void SendMessageSucceeded(object sender, SendMessageResultEventArgs e)
        {
            Response.Write(string.Format("\nSuccessfully sent message #{0}", e.Message.Tag.ToString()));
            if (e.RetryCount > 0)
                Response.Write(string.Format(" after {0} retries", e.RetryCount));

            device.NumberOfMessagesToSend--;
            Response.Write("\n");
        }

        private void SendMessageFailed(object sender, SendMessageResultEventArgs e)
        {
            Response.Write(string.Format("\nFailed to send message #{0} after {1} retries.\n", e.Message.Tag.ToString(), e.RetryCount));
        }

        #endregion
    }
}
